﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using CSCV.Group8.BlogRollWebPart.Helper;

namespace CSCV.Group8.BlogRollWebPart.Model
{
    /// <summary>
    /// Model layer of Blog Roll Web Part , Implement the IBRModel Interface
    /// </summary>
    public class BRModel : CSCV.Group8.BlogRollWebPart.Interface.IBRModel
    {

        #region field
        private List<string> _listblogurl; //List of blog url provided by user
        private List<SPList> _listbloglist; //List of SPList represent the blog
        #endregion

        #region prop

        /// <summary>
        /// List of splist of blog sites
        /// </summary>
        public List<SPList> ListBlogList
        {
            get
            {
                return this._listbloglist;
            }
            set
            {
                this._listbloglist = value;
            }
        }

        /// <summary>
        /// Number of Post
        /// </summary>
        public int IntNumberOfPost { get; set; }

        /// <summary>
        /// Number of words per post
        /// </summary>
        public int IntNumberOfWordPerPost { get; set; }

        /// <summary>
        /// Is show avatar
        /// </summary>
        public bool BoolShowAvatar { get; set; }

        /// <summary>
        /// String that contain the url provided by user
        /// </summary>
        public string StrBlogUrl { get; set; }

        /// <summary>
        /// //List of blog url provided by user
        /// </summary>
        public List<string> ListURL
        {
            get { return _listblogurl; }
        }

        #endregion

        #region ctor

        /// <summary>
        /// Create the model with specific prop
        /// </summary>
        /// <param name="strBlogUrl">string of blog urls provided by user, separate by comma </param>
        /// <param name="iNumberOfPost">number of post to be show</param>
        /// <param name="iNumberOfWordPerPost">number of word per post to be show</param>
        /// <param name="boolShowAvatar">is show/hide avatar</param>
        public BRModel(string strBlogUrl, int iNumberOfPost, int iNumberOfWordPerPost, bool boolShowAvatar)
        {
            this.IntNumberOfPost = iNumberOfPost;
            this.IntNumberOfWordPerPost = iNumberOfWordPerPost;
            this.BoolShowAvatar = boolShowAvatar;
            this.StrBlogUrl = strBlogUrl;
            List<string> UrlList = GetBlogUrlList(StrBlogUrl); //Set the list blog urls
            this._listblogurl = GetExistSPWeb(UrlList); //Check the valid blog urls
            _listbloglist = GetSPListFromUrl(_listblogurl); //Set the SPList[Posts] of each blog url
        }

        #endregion

        #region method

        /// <summary>
        /// Check the list of string is valid blog url, then return the valid one
        /// </summary>
        /// <param name="source">List of url need to validate</param>
        /// <returns>List of all valid blog URLs</returns>
        private List<string> GetExistSPWeb(List<string> source)
        {
            List<string> list = new List<string>();
            for (int i = 0; i < source.Count; i++)
            {
                string s = source[i];
                if (HelperLib.CheckSPSiteisABlog(s))
                {
                    list.Add(s);
                }
            }
            return list;
        }

        /// <summary>
        /// Get List BRPost object from a SplistItemCollection, auto provide a idcounter
        /// </summary>
        /// <param name="lst">A SPlistitemCollection</param>
        /// <param name="idcounter">input ID, can be changed</param>
        /// <returns>List of BRPost object</returns>
        private List<BRPost> GetPostFromCollection(SPListItemCollection lst)
        {
            List<BRPost> lstPost = new List<BRPost>();
            for (int i = 0; i < lst.Count; i++)
            {
                SPListItem spli = lst[i];
                BRPost p = new BRPost(spli, lst.List.ParentWeb.Url, BoolShowAvatar);
                //idcounter++;
                lstPost.Add(p);
            }
            return lstPost;
        }

        /// <summary>
        /// Get the list of SPListItemCollection from the List of SPlist
        /// </summary>
        /// <param name="lst">List of SPList of each Blog Url</param>
        /// <param name="n">Number of Post per blog</param>
        /// <returns>List of SPListItemCollection</returns>
        private List<SPListItemCollection> GetPostCollection(List<SPList> lst, int n)
        {
            List<SPListItemCollection> myPostCollection = new List<SPListItemCollection>();
            for (int i = 0; i < lst.Count; i++)
            {
                SPList spl = lst[i];
                SPQuery query = new SPQuery();
                query.Query = String.Format("<OrderBy><FieldRef Name='{0}' Ascending='{1}' /></OrderBy><RowLimit>{2}</RowLimit>", HelperConst.CREATED_TAG, HelperConst.FALSE_STRING_TAG, n);
                myPostCollection.Add(spl.GetItems(query));
            }
            return myPostCollection;
        }

        /// <summary>
        /// Get lastest N posts with each blogpage,
        /// </summary>
        /// <param name="n">Number of post per blog</param>
        /// <returns>List of post object</returns>
        private List<BRPost> GetLastestNPostPerBlog(List<SPList> lst, int n)
        {
            List<SPListItemCollection> myCollection = GetPostCollection(lst, n);
            List<BRPost> myListPost = new List<BRPost>();
            for (int i = 0; i < myCollection.Count; i++)
            {
                SPListItemCollection cc = myCollection[i];
                List<BRPost> temp = GetPostFromCollection(cc);
                for (int j = 0; j < temp.Count; j++)
                    myListPost.Add(temp[j]);
            }
            return myListPost;
        }

        /// <summary>
        /// Get the lastest post from the list of post
        /// </summary>
        /// <param name="source">list of BRPost</param>
        /// <returns>the lastest post</returns>
        private BRPost GetLastestPost(List<BRPost> source)
        {
            int index = 0;
            for (int i = 0; i < source.Count; i++)
            {
                if (source[index].PublishedDate.CompareTo(source[i].PublishedDate) < 0)
                {
                    index = i;
                }
            }
            return source[index];
        }

        /// <summary>
        /// From the list of blog urls, get the SPList of each one then return the List of SPList
        /// </summary>
        /// <param name="_listblogurl">List of blog url</param>
        /// <returns>the list of SPList</returns>
        private List<SPList> GetSPListFromUrl(List<string> _lstblogurl)
        {
            if (_lstblogurl.Count <= 0)
                return null;
            List<SPList> lst = new List<SPList>();
            for (int i = 0; i < _lstblogurl.Count; i++)
            {
                string str = _lstblogurl[i];
                using (SPSite sitecolection = new SPSite(str))
                {
                    SPWeb web = sitecolection.OpenWeb();
                    SPList olist = web.Lists.TryGetList(HelperConst.POST_LIST_TAG);
                    //this._listbloglist.Add(olist);
                    lst.Add(olist);
                }
            }
            return lst;
        }

        /// <summary>
        /// Load the comment of each Post to the list of Posts
        /// </summary>
        /// <param name="result">the list of post need to load the comment</param>
        /// <returns>the new list of post which have their comment</returns>
        private List<BRPost> GetCommentsForEachPost(List<BRPost> result)
        {
            for (int i = 0; i < result.Count; i++)
            {
                
                BRPost post = result[i];
                using (SPSite site = new SPSite(post.PostSPWebUrl))
                {
                    SPWeb web = site.OpenWeb();
                    SPList spList = web.Lists.TryGetList(HelperConst.COMMENT_TAG);
                    SPQuery query = new SPQuery();
                    query.Query = string.Concat("<Where><Eq>",
                                     string.Format("<FieldRef Name='{0}'/>", HelperConst.POST_ID_TAG),
                                     "<Value Type='LOOKUP'>", post.PostID, "</Value>",
                                  "</Eq></Where>",
                                  "<OrderBy>",
                                     string.Format("<FieldRef Name='{0}' Ascending='{1}' />", HelperConst.MODIFIED_TAG, HelperConst.FALSE_STRING_TAG),
                                  "</OrderBy>");
                    SPListItemCollection collection = spList.GetItems(query);
                    //Parse the SPListItem to Comment model.
                    List<Model.BRComment> lstComment = new List<BRComment>();
                    for (int j = 0; j < collection.Count; j++)
                    {
                        SPListItem listItem = collection[j];
                        Model.BRComment comment = new BRComment(listItem, post.PostID);
                        lstComment.Add(comment);
                    }
                    //Add list comment to Post
                    post.Comments = lstComment;
                }
            }
            return result;
        }

        /// <summary>
        /// Add the comment to the post
        /// </summary>
        /// <param name="commentContent">Body of the comment</param>
        /// <param name="postID">PostID of the comment</param>
        /// <param name="strspweburl">the SPWeb Url of the post</param>
        public void AddComment(string commentContent, string commentTitle, int postID, string strspweburl)
        {
            using (SPSite sitecolection = new SPSite(strspweburl))
            {
                SPWeb web = sitecolection.OpenWeb();
                try
                {
                    web.AllowUnsafeUpdates = true;
                    SPList objPostList = web.Lists.TryGetList(HelperConst.POST_LIST_TAG);
                    SPListItem objPost = objPostList.GetItemById(postID);
                    SPList objCommentsList = web.Lists.TryGetList(HelperConst.COMMENT_TAG);
                    SPListItem objNewComment = objCommentsList.Items.Add();
                    if (string.IsNullOrEmpty(commentTitle))
                        objNewComment[HelperConst.TITLE_TAG] = HelperConst.DEFAULT_COMMENT_TITLE_PREFIX_TAG + Convert.ToString(objPost[HelperConst.TITLE_TAG]);
                    else
                        objNewComment[HelperConst.TITLE_TAG] = commentTitle;
                    objNewComment[HelperConst.COMMENT_CONTENT_TAG] = commentContent;
                    objNewComment[HelperConst.POST_TITLE_TAG] = postID + HelperConst.DEFAULT_COMMENT_TITLE_SPLIT_TAG + Convert.ToString(objPost[HelperConst.TITLE_TAG]);
                    objNewComment.Update();
                    web.AllowUnsafeUpdates = false;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }

        /// <summary>
        /// Get lastest posts from SOM
        /// </summary>
        /// <param name="n">number of post to get</param>
        /// <returns>list of BRPost</returns>
        public List<BRPost> GetLastestNPost(int n)
        {
            try
            {
                if (_listbloglist == null)
                {
                    _listbloglist = GetSPListFromUrl(_listblogurl);
                }
                List<BRPost> lst = GetLastestNPostPerBlog(_listbloglist, n);
                List<BRPost> result = new List<BRPost>();
                int i = 0;
                while (i < n && lst.Count > 0)
                {
                    BRPost p = GetLastestPost(lst);
                    lst.Remove(p);
                    result.Add(p);
                    i++;
                }
                //Load comments to posts
                result = GetCommentsForEachPost(result);
                return result;

            }
            catch (Exception ex)
            {
                throw ex;

            }

        }

        /// <summary>
        /// Set the list of url to blog url
        /// </summary>
        /// <param name="urlList"></param>
        public void SetUrlList(List<string> urlList)
        {
            this._listblogurl = GetExistSPWeb(urlList);
        }

        /// <summary>
        /// The method call to return the lastest blog post from the user configuration
        /// </summary>
        /// <returns></returns>
        public List<BRPost> Init()
        {
            if (IntNumberOfPost > 0 && !string.IsNullOrEmpty(StrBlogUrl) && _listbloglist != null)
            {
                //Get this list with Full words in BODY
                List<Model.BRPost> temp = GetLastestNPost(IntNumberOfPost);
                //Substring the body to fit the number of word which user request to be display.
                foreach (Model.BRPost post in temp)
                {
                    string strStripedContent = Helper.HelperLib.StripHTML(post.Content);
                    if (strStripedContent.Length > IntNumberOfWordPerPost && IntNumberOfWordPerPost >= 0)
                    {
                        if (IntNumberOfWordPerPost == 0)
                            post.Content = HelperConst.EMPTY_STRING_TAG;
                        else
                        {
                            post.Content = strStripedContent.Substring(0, IntNumberOfWordPerPost) + HelperConst.MORE_STRING_TAG;
                        }
                    }
                }
                return temp;
            }
            else
                return new List<Model.BRPost>();
        }

        /// <summary>
        /// Convert the url string (separate by comma) to the string list
        /// </summary>
        /// <param name="strBlogUrl">blogs url (separate by comma)</param>
        /// <returns>the string list contain the blog urls</returns>
        public System.Collections.Generic.List<string> GetBlogUrlList(string strBlogUrl)
        {
            System.Collections.Generic.List<string> ListBlogUrl = new System.Collections.Generic.List<string>();
            if (strBlogUrl != null && strBlogUrl != string.Empty)
            {

                String[] StrTmp = strBlogUrl.Split(',');
                for (int i = 0; i < StrTmp.Length; i++)
                {
                    StrTmp[i] = StrTmp[i].Trim();
                    ListBlogUrl.Add(StrTmp[i]);
                }
            }
            return ListBlogUrl;
        }
        #endregion
    }
}
